﻿//#define LoadADB
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
#endif
[System.Serializable]
public class DespawnObj{
	public GameObject _model;
	public float _time;
	public DespawnObj(GameObject target,float time,bool isUI){
		target.transform.parent = isUI?ObjManager.Instance.ReadyDespawnUIParent:ObjManager.Instance.ReadyDespawnParent ;
		_model = target;
		_time = time;
	}
}
public class ObjManager : ModuleComponent<ObjManager> {
	#region Static
	private Transform objPool = null;
	Transform readyDespawnUIParent;
	public Transform ReadyDespawnUIParent{
		get{
			if (readyDespawnUIParent == null) {
				readyDespawnUIParent = new GameObject ("readyDespawnUIParent").transform;
				readyDespawnUIParent.parent = ParentUI;
				readyDespawnUIParent.localPosition = Vector3.zero;
				readyDespawnUIParent.localScale = Vector3.one;
			}
			return readyDespawnUIParent;
		}
	}
	Transform readyDespawnParent;
	public Transform ReadyDespawnParent{
		get{ 
			if (readyDespawnParent == null) {
				readyDespawnParent = new GameObject ("readyDespawnParent").transform;
				readyDespawnParent.parent = ParentDefualt;
				readyDespawnParent.localPosition = Vector3.zero;
				readyDespawnParent.localScale = Vector3.one;
			}
			return readyDespawnParent;
		}
	}
	public Transform ParentDefualt{
		get{
			if(objPool == null){
				objPool = new GameObject("ObjPool").transform;
				objPool.parent = ObjManager.Instance.transform;
				objPool.transform.localPosition = Vector3.one * 1000;
			}
			return objPool;
		}
	}
	private Transform uiPool = null;
	public Transform ParentUI{
		get{
			if(uiPool == null){
				uiPool = new GameObject("UIPool").transform;
				if(GameObject.FindObjectOfType<UIRoot> ()!=null){
					uiPool.parent = GameObject.FindObjectOfType<UIRoot> ().transform;
					uiPool.transform.localPosition = Vector3.one * 1000;
					uiPool.transform.localScale = Vector3.one;
				}
			}
			return uiPool;
		}
	}
	static public void SetParent(Transform value,Transform target){
		if (value != null) {
			value.parent = target;
		}
	}
	static public void SetParentAndRest(Transform value,Transform target){
		if (value != null && target != null) {
//			value.SetParent (target);
			value.transform.parent = target;
			value.localPosition = Vector3.zero;
			value.localEulerAngles = Vector3.zero;
			value.localScale = Vector3.one;
		}
	}
	#endregion
	#region Path
    
	/// <summary>
	/// Assets/Prefab 警告： 通常不需要调用这个	
	/// </summary>
	public string PathMain = "Assets/Prefab/";
	public string PathUIPanel = "ViewUI/";
	public string PathModel = "Model/";
	public string PathEffect = "PrefabEffect/";
	#endregion
	private Dictionary<string,ObjPool> Pool = new Dictionary<string, ObjPool>();
	List<DespawnObj> _despawn = new List<DespawnObj>();
	public GameObject AddChild(string path,Transform parent = null){
		GameObject asset;
		#if UNITY_EDITOR && LoadADB
		asset = AssetDatabase.LoadAssetAtPath(ObjManager.Instance.PathMain+path+".prefab",typeof(GameObject)) as GameObject;
#else 
		asset = Resources.Load<GameObject>(path);
#endif
		return AddChild (asset, parent);
	}
	public GameObject AddChildByPool(GameObject perfab,Transform parent,Transform poolparent,float deletime =0 ){
		if (!Pool.ContainsKey (perfab.name)) {
			Pool.Add (perfab.name, new ObjPool (perfab, parent, poolparent));
		}
		GameObject obj = Pool [perfab.name].getObj (perfab.name);
		if (obj == null)
			Debug.Log ("obj is null");
		ObjManager.SetParentAndRest (obj.transform, parent);
        if (deletime != 0) {
			Despawn (obj,deletime,poolparent == ParentUI);
		}
		return obj;
	}
	public GameObject AddChild(GameObject parent,Transform target,float deletime =0){
		GameObject newobj = GameObject.Instantiate (parent);
		newobj.transform.parent = target;
//		if (deletime != 0) {
//			Despawn (newobj,deletime);
//		}
		return newobj;
	}
	public ParticleSystem AddEffect(string name,Transform parent,float deletime = 0){
		GameObject effectobj = AddChild (PathModel, name, parent, ParentDefualt, deletime);
		ParticleSystem _effect = effectobj.GetComponentInChildren<ParticleSystem> ();
		_effect.Play ();
		return _effect;
	}
	public void DespawnEffect(ParticleSystem effect,float deletime = 0){
		effect.Stop ();
		Despawn (effect.gameObject, deletime);
	}

	public GameObject AddChild(string path,string name,Transform parent = null,Transform poolparent = null,float deletime =0 ){
		if(poolparent == null)
			poolparent = ParentDefualt;
		if (!Pool.ContainsKey (name)) {
			Pool.Add (name,new ObjPool(path,name,parent,poolparent));
		}
		GameObject obj = Pool [name].getObj (path);
		if (obj == null)
			return null;
		ObjManager.SetParentAndRest (obj.transform, parent);
		if (obj!=null && deletime != 0)
			Despawn (obj, deletime,poolparent == ParentUI);
		return obj;
	}
	public void Despawn(GameObject target,float time = 0,bool isui = false){
		if (time == 0) {
			target.SetActive (false);
			if (Pool.ContainsKey (target.name))
				Pool [target.name].Recycle (target);
			else {
				if (Application.isPlaying) {
					GameObject.Destroy (target);
				} else
					GameObject.DestroyImmediate (target);
			}
		} else {
			_despawn.Add(new DespawnObj(target,time,isui));
		}
	}
	public bool IsContainsObj(GameObject target){
		return Pool.ContainsKey (target.name);
	}
	public void Update(){
//		if (Time.frameCount % 5 == 0) {
			for (int i = 0; i < _despawn.Count; i++) {
				_despawn [i]._time =_despawn [i]._time- Time.deltaTime;
				if (_despawn [i]._time <= 0) {
					Despawn (_despawn [i]._model);
					_despawn.RemoveAt (i);
					i++;
				}
			}
//		}
	}
}
[System.Serializable]
public class ObjPool{
	private GameObject prefab;
	private string _path;
	private Transform poolParent;
	private System.Collections.Generic.List<GameObject> pool;
	public ObjPool(GameObject _perfab,Transform parent,Transform poolparent){
		GameObject newobj;
		prefab = _perfab;
		_path = prefab.name;
		_perfab.SetActive (false);
		poolParent = poolparent;
		pool = new List<GameObject> ();
		newobj = GameObject.Instantiate(prefab);
		newobj.transform.parent = poolparent;
		pool.Add (prefab);
	}
	public ObjPool(string path,string name,Transform parent,Transform poolparent){
		_path = path;
		GameObject newobj = null;
#if UNITY_EDITOR && UseADB
		prefab = AssetDatabase.LoadAssetAtPath(ObjManager.Instance.PathMain+path+name+".prefab",typeof(GameObject)) as GameObject;
#else
		prefab = Resources.Load(path+name) as GameObject;
		#endif
		if(prefab == null){
			Debug.Log("LoadAssetAtPath Obj Fial:"+path+name);
		}
		else{
			newobj = GameObject.Instantiate(prefab);
		}
		if (newobj != null) {
			poolParent = poolparent;
			newobj.name = name;
			pool = new List<GameObject> ();
			newobj.SetActive (false);
			ObjManager.SetParent (newobj.transform, poolparent);
			pool.Add (newobj);
		} else {
			Debug.Log("Create Obj Fial:"+path+name);
		}
	}
	private void AddChild(){
		if (prefab != null) {
			GameObject newobj = GameObject.Instantiate (prefab);
			newobj.name = prefab.name;
			pool.Add (newobj);
		} 
	}
	public GameObject getObj(string path){
		if (_path != path) {
			Debug.Log ("路径重复:old"+_path+" now:"+path);
			return null;
		}
		if (pool == null || pool.Count == 0) {
			AddChild();
		}
		GameObject value = pool [0];
		value.SetActive (true);
		pool.RemoveAt (0);
		return value;
	}
	//回收
	public void Recycle(GameObject target){
		target.transform.parent = poolParent;
		target.transform.localPosition = Vector3.zero;
		target.SetActive (false);
		pool.Add (target);
	}
}
